package com.hgkj.system.service.impl;

import com.hgkj.common.core.constant.DictConstant;
import com.hgkj.common.core.utils.AssertExceptionUtils;
import com.hgkj.system.domain.SysMenu;
import com.hgkj.system.domain.vo.MetaVo;
import com.hgkj.system.domain.vo.RouterVo;
import com.hgkj.system.mapper.SysMenuMapper;
import com.hgkj.system.mapper.SysRoleMenuMapper;
import com.hgkj.system.service.SysMenuService;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.util.*;
import java.util.stream.Collectors;

@Service
public class SysMenuServiceImpl implements SysMenuService {

    private final SysMenuMapper sysMenuMapper;
    private final SysRoleMenuMapper sysRoleMenuMapper;

    public SysMenuServiceImpl(SysMenuMapper sysMenuMapper, SysRoleMenuMapper sysRoleMenuMapper) {
        this.sysMenuMapper = sysMenuMapper;
        this.sysRoleMenuMapper = sysRoleMenuMapper;
    }

    /**
     * 根据角色集合查询权限集合
     *
     * @param roleList 角色集合
     * @return 权限集合
     */
    @Override
    public Set<String> getPermsByRoles(List<String> roleList) {
        return sysMenuMapper.selectPermsByRoleIds(roleList);
    }

    /**
     * 获取所有路由信息
     *
     * @return 所有路由信息
     */
    @Override
    public List<SysMenu> getAllRouters() {
        List<SysMenu> menuList = sysMenuMapper.selectAllSysMenu();
        return buildMenuTreeNonRecursive(menuList);
    }

    /**
     * 获取菜单路由信息
     *
     * @param userId 用户ID
     * @return 菜单集合
     */
    @Override
    public List<SysMenu> getRoutersByUserId(Long userId) {
        List<SysMenu> menuList = sysMenuMapper.selectSysMenuByUserId(userId);
        return buildMenuTreeNonRecursive(menuList);
    }

    /**
     * 构建可返回前端的路由对象
     *
     * @param menuList 树形数据
     * @return routers
     */
    @Override
    public List<RouterVo> buildMenus(List<SysMenu> menuList) {
        List<RouterVo> routers = new LinkedList<>();
        for (SysMenu sysMenu : menuList) {
            RouterVo router = new RouterVo();
            router.setName(StringUtils.capitalize(sysMenu.getPath()));
            router.setPath("/" + sysMenu.getPath());
            router.setQuery(sysMenu.getQuery());
            router.setMeta(new MetaVo(sysMenu.getTitle(), sysMenu.getIcon(), sysMenu.getMenuName()));
            router.setHidden(DictConstant.IS_VISIBLE.equals(sysMenu.getVisible()));
            router.setComponent(sysMenu.getMenuType().equals(DictConstant.TYPE_DIR) ? DictConstant.LAYOUT : sysMenu.getComponent());
            List<SysMenu> children = sysMenu.getChildren();
            if (!children.isEmpty() && DictConstant.TYPE_DIR.equals(sysMenu.getMenuType())) {
                if (children.size() == 1) {
                    router.setPath("/" + sysMenu.getPath() + "/" + children.get(0).getPath());
                }
                router.setChildren(buildMenus(sysMenu.getChildren()));
            }
            routers.add(router);
        }
        return routers;
    }

    /**
     * 新增菜单
     *
     * @param sysMenu data
     * @return rows
     */
    @Override
    public int insertMenu(SysMenu sysMenu) {
        SysMenu dbMenu = sysMenuMapper.selectSysMenuByMenuName(sysMenu.getMenuName());
        AssertExceptionUtils.mustNull(dbMenu, "菜单名不允许重复");
        sysMenu.initInsertPropriety();
        return sysMenuMapper.insertMenu(sysMenu);
    }

    /**
     * 修改菜单
     *
     * @param sysMenu 菜单数据
     * @return rows
     */
    @Override
    public int editMenu(SysMenu sysMenu) {
        SysMenu dbMenu = sysMenuMapper.selectSysMenuByMenuName(sysMenu.getMenuName());
        if (!Objects.isNull(dbMenu)) {
            AssertExceptionUtils.mustEquals(sysMenu.getMenuId(), dbMenu.getMenuId(), "菜单名重复");
        }
        sysMenu.initUpdatePropriety();
        return sysMenuMapper.editMenu(sysMenu);
    }

    /**
     * 根据菜单ID删除菜单
     *
     * @param menuId menuId
     * @return rows
     */
    @Override
    public int deleteMenuById(Long menuId) {
        AssertExceptionUtils.notFalse(!hasChildrenByMenuId(menuId), "存在子节点不允许删除");
        AssertExceptionUtils.notFalse(!checkMenuExistRole(menuId), "已分配角色，不允许删除");
        return sysMenuMapper.removeMenuByMenuId(menuId);
    }

    /**
     * 判断是否有子节点
     *
     * @param menuId menuId
     * @return boolean
     */
    @Override
    public boolean hasChildrenByMenuId(Long menuId) {
        return sysMenuMapper.countChildByMenuId(menuId) > 0;
    }

    /**
     * 检查是否分配给了角色
     *
     * @param menuId menuId
     * @return boolean
     */
    @Override
    public boolean checkMenuExistRole(Long menuId) {
        return sysRoleMenuMapper.checkMenuExistRole(menuId) > 0;
    }

    @Override
    public List<SysMenu> listMenu() {
        return buildMenuTreeNonRecursive(sysMenuMapper.selectAllTypeSysMenu());
    }

    /**
     * 非递归方式构建菜单树
     */
    public List<SysMenu> buildMenuTreeNonRecursive(List<SysMenu> menuList) {
        if (menuList == null || menuList.isEmpty()) {
            return Collections.emptyList();
        }

        // 构建menuId到菜单的映射
        Map<Long, SysMenu> menuMap = menuList.stream()
                .peek(menu -> menu.setChildren(new ArrayList<>()))
                .collect(Collectors.toMap(SysMenu::getMenuId, menu -> menu));

        List<SysMenu> tree = new ArrayList<>();
        for (SysMenu menu : menuList) {
            Long parentId = menu.getParentId();
            if ((long) parentId == DictConstant.parentId) {
                // 顶级菜单直接加入树
                tree.add(menu);
            } else {
                // 找到父菜单并添加到子菜单列表
                if (menuMap.containsKey(parentId)) {
                    SysMenu parentMenu = menuMap.get(parentId);
                    parentMenu.getChildren().add(menu);
                }
            }
        }
        return tree;
    }

}
